home *** CD-ROM | disk | FTP | other *** search
- /*
- * Cylinder.C - methods for cylinder manipulations.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * University of Berne, Switzerland
- * Copyright (C) 1989, 1991, Craig E. Kolb
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "Cylinder.h"
- #include "transform.h"
-
- //___________________________________________________________ Cylinder
-
- Cylinder::Cylinder(real radius, const Vector& bottom, const Vector& top)
- {
- Vector axis = top - bottom;
- real len = axis.normalize();
-
- /*
- * matrix trans transforms unit cylinder (1, [0,0,0], [0,0,1]) to
- * the given cylinder (radius, bottom, top).
- */
- trans = new TransMatrix(coordSystemTransform(bottom, axis,
- radius, len));
- itrans = new TransMatrix(*trans);
- itrans->invert();
- }
-
- GeoObject* Cylinder::create(real radius, const Vector& bottom, const Vector& top)
- {
- if (radius < EPSILON)
- return NULL;
-
- if ((top-bottom).length() < EPSILON)
- return NULL;
-
- return new Cylinder(radius, bottom, top);
- }
-
- /*
- * Ray cylinder intersection.
- *
- * The code is adapted from Craig Kolbs rayshade.
- */
-
- int Cylinder::intersect(const Ray& ray, real minDist, real& maxDist)
- {
- real t1, t2, a, b, c, zpos1, zpos2, disc;
-
- intersectionTests++;
-
- a = ray.getDir()[0]*ray.getDir()[0] + ray.getDir()[1]*ray.getDir()[1];
- if (a < EPSILON*EPSILON)
- /* |ray.getDir()[2]| == 1. */
- return FALSE;
-
- b = ray.getDir()[0]*ray.getOrig()[0]
- + ray.getDir()[1]*ray.getOrig()[1];
- c = ray.getOrig()[0]*ray.getOrig()[0]
- + ray.getOrig()[1]*ray.getOrig()[1] - 1;
- disc = b*b - a*c;
-
- if(disc < 0.)
- return FALSE;
-
- disc = sqrt(disc);
- t1 = (-b + disc) / a;
- t2 = (-b - disc) / a;
- if (t1 < minDist && t2 < minDist)
- return FALSE;
-
- zpos1 = ray.getOrig()[2] + t1 * ray.getDir()[2];
- zpos2 = ray.getOrig()[2] + t2 * ray.getDir()[2];
-
- if (t1 < minDist || zpos1 < 0. || zpos1 > 1.) {
- if (t2 < minDist || zpos2 < 0. || zpos2 > 1.)
- return FALSE;
- else
- t1 = t2;
- }
- else if (t2 >= minDist && zpos2 >= 0. && zpos2 <= 1.)
- t1 = (t1 < t2) ? t1 : t2;
-
- if (t1 < maxDist) {
- maxDist = t1;
- intersections++;
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- * Compute cylinder normal at the given point.
- */
-
- Vector Cylinder::normal(const Vector& p) const
- {
- /*
- * The normal is equal to the point of intersection in cylinder
- * space, but with Z = 0.;
- */
- return Vector(p[0], p[1], 0);
- }
-
- /*
- * Split the cylinder into polygon (rectangles)
- */
-
- PolygonList* Cylinder::tesselate(const BoundingBox&)
- {
- const int resolution = 10;
- real delta = 2*M_PI/(real)resolution;
- real lastX = 1;
- real lastY = 0;
- real x, y;
-
- Polygon* p;
- PolygonList* polys = new PolygonList(resolution);
-
- /*
- * generate points on the edge of the disc.
- */
-
- for (real alpha=delta; alpha <= 2*M_PI; alpha += delta) {
- x = cos(alpha); y = sin(alpha);
- p = new Polygon(Vector(lastX, lastY, 0), Vector(x, y, 0),
- Vector(x, y, 1), Vector(lastX, lastY, 1));
- p->transform(*trans);
- polys->append(p);
- lastX = x; lastY = y;
- }
-
- return polys;
- }
-
- /*
- * If a transformation is given for the defined cylinder, postmultiply
- * it to the already computed transformations.
- */
-
- int Cylinder::setTransform(TransMatrix* tmat)
- {
- TransMatrix* matMul = new TransMatrix((*trans) * (*tmat));
- delete itrans;
- delete trans;
-
- return GeoObject::setTransform(matMul);
- }
-
-
-
-